# -*- coding = utf-8 -*-
# @Time : 2022/10/18 14:52
# @Author :Henry L
# @File : OrganizationTypeSpider.py
# @Software : PyCharm
import io
import json
import random
import time
import uuid
import requests
from urllib.parse import quote_plus
from PIL import Image
from bs4 import BeautifulSoup
import setting
from datetime import datetime
from Utils import Unil


class OrganizationTypeSpider():
    """
    机构搜索类爬虫
    """

    def __init__(self,proxy):
        proxy_url = f'http://{proxy}'
        self.proxy = {"http": proxy_url, "https": proxy_url}
        self.url = "http://zgcx.nhc.gov.cn:9090/unit"
        self.session = requests.session()
        self.host = "http://zgcx.nhc.gov.cn:9090/"
        self.util = Unil()
        self.start_time = datetime.now().replace(hour=0, minute=45, second=0)
        self.end_time = datetime.now().replace(hour=5, minute=30, second=0)
        self.uuid = uuid.uuid4()
        self.UA = random.choice(setting.USER_AGENT_LIST)
        self.header = {
            "User-Agent": self.UA,
            "Upgrade-Insecure-Requests":'1',
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
            "Host": "zgcx.nhc.gov.cn:9090",
            "If-Modified-Since": "Thu, 18 Apr 2024 04:22:17 GMT",
            "Accept-Encoding": "gzip, deflate",
        }
        self.flag = {"unitName": "name",
                     "unitGuid": "id",
                     "province": "wjw_province",
                     "unitOrganName": "approval_company",
                     "unitRegCode": "register",
                     "unitAddr": "address",
                     "unitSubjectName": "department",
                     "unitLevelName": "grade",
                     "unitLegalName": "legal_person",
                     "unitChargeName": "manager",
                     "unitDateValidBegin": "licence_date_begin",
                     "unitDateValidEnd": "licence_date_end",
                     "unitHavingName": "hos_nature",
                     "unitNatureBusiName": "hos_nature_",
                     "unitPassDate": "back_date",
                     "unitServiceType": "service_part"
                     }
        self.doc_flag = {"姓名：": "name",
                         "性别：": "sex",
                         "医师级别：": "approval_company",
                         "执业类别：": "job_type",
                         "执业地点：": "job_address",
                         "执业证书编码：": "register",
                         "主要执业机构：": "company",
                         "执业范围：": "range",
                         "发证(批准)机关：": "approval",
                         "多机构备案信息：": "ifMore",
                         "机构名称": "approval_company_",
                         "有效期": "effective_",
                         "备案机关": "back_",
                         "机构名称有效期备案机关": "more",
                         "美容主诊医师专业：": "beautified",
                         "医师类别：": "doctor_type",
                         "医师专业：": "doctor_pro",
                         "执业范围：中医药技术方法": "range",
                         "治疗病症范围：": "range",
                         }

    def isduringthattime(self):
        now_time = datetime.now()
        if self.start_time <= now_time <= self.end_time:
            diff45 = self.end_time - now_time
            time.sleep(diff45.seconds)

    def run(self, pro, name, util):
        """
        获取列表页数据
        :param pic:
        :param util:
        :param pro: 省
        :param name: 名称
        :return:
        """
        self.isduringthattime()
        value = ""
        try:
            # 验证码
            token = ""
            check_str = {}
            status = '0'
            while status != '成功':
                check_str, token, point_json = self.get_location(util)
                check_res = self.GetIsPass(check_str)
                status = json.loads(check_res)['msg']
            payload = {
                "provinceCode": setting.PROVINCE_CODE_MAP[pro],
                "unitName": name,
            }
            header = {
                "Accept": "application/json, text/plain, */*",
                "Accept-Encoding": "gzip, deflate",
                "Accept-Language": "zh-CN,zh;q=0.9",
                "checkWordToken": token,
                "Connection": "keep-alive",
                "Content-Type": "application/json",
                "Host": "zgcx.nhc.gov.cn:9090",
                "Origin": "http://zgcx.nhc.gov.cn:9090",
                "pointJson": check_str['pointJson'],
                "Referer": "http://zgcx.nhc.gov.cn:9090/unit",
                "User-Agent": self.UA,
            }
            response = requests.post(url="http://zgcx.nhc.gov.cn:9090/DATA/web/unit/list", json=payload, proxies=self.proxy,headers=header, timeout=(6.2, 62)).text
            data = json.loads(response)
            if data['msg'] != "成功":
                return 'WRONG'
            return data
        except Exception as e:
            return "WRONG"

    def run_doc(self, pro, doc_name, hos_name, util):
        """
        获取列表页数据
        :param pic:
        :param util:
        :param pro: 省
        :param name: 名称
        :return:
        """
        self.isduringthattime()
        self.url = "http://61.49.18.120:9090/Doctor"
        value = ""
        hos_name = '〇〇〇〇'
        try:
            res = self.session.get(self.url, headers=self.header)
            if res.status_code != 200:
                return "NOT FOUND"
            # 验证码
            status = '0'
            jsons = []
            while status != '成功':
                jsons = self.get_location(util)
                check_res = self.GetIsPass(jsons)
                status = json.loads(check_res)['msg']
            soup = BeautifulSoup(res.content, 'lxml')
            for el in soup.findAll("input"):
                if el.get("name") == "__RequestVerificationToken":
                    value = el.get("value")
            payload = {
                "Prov": setting.PROVINCE_CODE_MAP[pro],
                "Doctor_Name": doc_name,
                "Zy_Unit": hos_name,
                "Check_Code": '{}@{}'.format(self.uuid, json).replace("'", '"').replace(' ', ''),
                "__RequestVerificationToken": value
            }
            data = self.session.post(self.url, data=payload, timeout=(6.2, 62))
            if type(data) == str:
                return 'WRONG'
            return data
        except requests.exceptions.ReadTimeout:
            time.sleep(10)
            return self.run_doc(pro, doc_name, hos_name, util)
        except requests.exceptions.Timeout:
            return self.run_doc(pro, doc_name, hos_name, util)
        except requests.exceptions.RequestException as e:
            return "WRONG"

    def get_code(self, util, pic):
        getVerCodePic = self.session.get(
            self.host + "ClickAPI/getVerCodePic?guid={}&width=400&height=150")
        img_byte = getVerCodePic.content
        image = Image.open(io.BytesIO(img_byte))
        image.save(pic)
        code = util.get(pic)
        return code

    def get_location(self, util):
        header = {
            "Accept": "application/json, text/plain, */*",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Connection": "keep-alive",
            "Content-Length": "26",
            "Content-Type": "application/json",
            "Host": "zgcx.nhc.gov.cn:9090",
            "Origin": "http://zgcx.nhc.gov.cn:9090",
            "Referer": "http://zgcx.nhc.gov.cn:9090/unit",
            "User-Agent": self.UA,
        }
        token = ''
        check_str = {}
        image_location_json = []
        while len(image_location_json) < 4:
            payload = {
                "width": 400,
                "height": 300
            }
            getVerCodePic = requests.post("http://zgcx.nhc.gov.cn:9090/DATA/image/validate/post4ValidImg", headers=header, json=payload,proxies=self.proxy)
            data = json.loads(getVerCodePic.text)
            if data['msg'] == "成功":
                token = data['data']['token']
                image_location_json = util.get_pic_location(text=getVerCodePic.text)
        check_str['token'] = token
        check_str['pointJson'] = '[' + str(image_location_json[0]) + ',' + str(image_location_json[1]) + ',' + str(image_location_json[2]) + ',' + str(image_location_json[3]) + ']'
        check_str['pointJson'] = check_str['pointJson'].replace("'", '"').replace(' ','')
        return check_str, token, image_location_json

    def GetIsPass(self, json):
        try:
            header = {
                "Accept": "application/json, text/plain, */*",
                "Accept-Encoding": "gzip, deflate",
                "Accept-Language": "zh-CN,zh;q=0.9",
                "Connection": "keep-alive",
                "Content-Length": "200",
                "Content-Type": "application/x-www-form-urlencoded",
                "Host": "zgcx.nhc.gov.cn:9090",
                "Origin": "http://zgcx.nhc.gov.cn:9090",
                "Referer": "http://zgcx.nhc.gov.cn:9090/unit",
                "User-Agent": self.UA,
            }
            url = "http://zgcx.nhc.gov.cn:9090/DATA/image/validate/check"
            payload = json
            res = requests.post(url=url, data=payload, headers=header, proxies=self.proxy)
            return res.text
        except:
            return "WRONG"


    def get(self, data):
        """
        获取详情页数据
        :param data:
        :return:
        """

        dt_list = []
        soup = BeautifulSoup(data.content, 'lxml')
        for a in soup.findAll("a"):
            dt = {}
            d_value = []
            d_title = []
            if "Details" in a.get("href"):
                _detail = self.session.get(self.host + a.get("href"))
                detail = BeautifulSoup(_detail.content, 'lxml')
                dt['name'] = detail.title.string
                for el in detail.find_all(class_='field_cxt'):
                    d_value.append(el.text.replace(' ', '').replace('\n', '').replace('\r', '').replace('\xa0', ''))
                for el in detail.find_all(class_='field_title'):
                    d_title.append(el.text.replace(' ', '').replace('\n', '').replace('\r', '').replace('\xa0', ''))
                for i in range(0, len(d_value)):
                    if i - len(d_title) >= 0:
                        dt[self.doc_flag[d_title[i]]] = d_value[i:]
                        break
                    dt[self.flag[d_title[i]]] = d_value[i]
                dt_list.append(dt)
                time.sleep(1)
        return dt_list

    def get_doc(self, data):
        """
        获取详情页数据
        :param data:
        :return:
        """
        time_sleepy = 1 + 0.1 * random.randint(0, 10)
        dt_list = []
        soup = BeautifulSoup(data.content, 'lxml')
        for a in soup.findAll("a"):
            dt = {}
            d_value = []
            d_title = []
            if "Details" in a.get("href"):
                _detail = self.session.get(self.host + a.get("href"))
                detail = BeautifulSoup(_detail.content, 'lxml')
                for el in detail.find_all(class_='field_cxt'):
                    d_value.append(el.text.replace(' ', '').replace('\n', '').replace('\r', '').replace('\xa0', ''))
                for i, el in enumerate(detail.find_all(class_='field_title')):
                    d_title.append(el.text.replace(' ', '').replace('\n', '').replace('\r', '').replace('\xa0', ''))
                for i in range(0, len(d_value)):
                    if i - len(d_title) + 1 >= 0:
                        dt[self.doc_flag[d_title[i]]] = d_value[i:]
                        break
                    dt[self.doc_flag[d_title[i]]] = d_value[i]
                el = detail.find_all(class_="text-center")
                if len(el) == 2:
                    dt["ifMore"] = "True"
                else:
                    dt["ifMore"] = "False"
                dt_list.append(dt)
                time.sleep(time_sleepy)
        return dt_list

    def available(self, data):
        if isinstance(data, str):
            return "WRONG"
        soup = BeautifulSoup(data.content, 'lxml')
        error = soup.find_all(class_="validation-summary-errors")
        if "Error" in data.url:
            return "WRONG"
        if len(error) > 0:
            if '受限' in error[0].text:
                return '受限'
            return "ERROR"
        none = soup.find_all(class_='text-danger')
        if len(none) != 0:
            return "未查询到"
        return "USUAL"

    def available_new(self, data):
        data_list = []
        try:
            if data['data'] is None:
                return "未查询到"
            if data['data']['summary']['total'] == '0':
                return "未查询到"
            for i in data['data']['unitInfoList']:
                stand_data = {}
                id = i['unitGuid']
                header = {
                    "Accept": "application/json, text/plain, */*",
                    "Accept-Encoding": "gzip, deflate",
                    "Accept-Language": "zh-CN,zh;q=0.9",
                    "Connection": "keep-alive",
                    "Content-Length": "0",
                    "Host": "zgcx.nhc.gov.cn:9090",
                    "id": id,
                    "Origin": "http://zgcx.nhc.gov.cn:9090",
                    "Referer": "http://zgcx.nhc.gov.cn:9090/unit",
                    "User-Agent": self.UA,
                }
                try:
                    res = requests.post(url="http://zgcx.nhc.gov.cn:9090/DATA/post4Ticket", headers=header,proxies=self.proxy)
                    res_data = json.loads(res.text)
                except Exception as e:
                    return "timeout"
                queryid = res_data["data"]
                header = {
                    "Accept": "application/json, text/plain, */*",
                    "Accept-Encoding": "gzip, deflate",
                    "Accept-Language": "zh-CN,zh;q=0.9",
                    "Connection": "keep-alive",
                    "Content-Length": "0",
                    "Host": "zgcx.nhc.gov.cn:9090",
                    "Origin": "http://zgcx.nhc.gov.cn:9090",
                    "Referer": "http://zgcx.nhc.gov.cn:9090/unit",
                    "User-Agent": self.UA,
                }
                try:
                    detail_res = requests.post(url="http://zgcx.nhc.gov.cn:9090/DATA/web/unit/detail/" + queryid, headers=header,proxies=self.proxy)
                    detail_data = json.loads(detail_res.text)
                except Exception as e:
                    return "timeout"
                if detail_data['msg'] == '成功':
                    detail_data = detail_data["data"]
                    for key in detail_data.keys():
                        if key in self.flag.keys():
                            stand_data[self.flag[key]] = detail_data[key]
                    data_list.append(stand_data)
            return data_list
        except Exception as e:
            return "timeout"
